#include <iostream>
#include <stdio.h>

#include "mockcpp/mockcpp.hpp"
#include "gtest/gtest.h"

#include "core_api.h"
#include "pub.h"

// setuptestcase fixture
// setup everycase

extern "C" {
extern int             RunDemo();
extern E_LOGLEVEL_TYPE g_LogLevel;
}

#define NOT_RUN_THREAD_POOL_UNIT_TEST

class CoreTest : public ::testing::Test {
  protected:
    virtual void SetUp() { std::cout << "setup executor" << std::endl; }
    virtual void TearDown()
    {
        std::cout << "teardown executor" << std::endl;
        GlobalMockObject::verify();
    }
    static void SetUpTestCase() { std::cout << "setup by case" << std::endl; }
    static void TearDownTestCase()
    {
        std::cout << "teardown by case" << std::endl;
    }
};

TEST_F(CoreTest, InitMsgAndSndMsg)
{
    // MOCKER(printf).stubs().expects(once());
    // MOCKER(HandleFuncOfLazyExec).expects(once());
    printf("init 1\n");
    ASSERT_EQ(CORE_TimerInit(), BEST_OK);
    printf("init 2\n");
    ASSERT_EQ(RunDemo(), 0);

    // MOCKER(FakeCallback).stubs().with(any(),
    // any()).will(returnValue(BEST_OK));
    // ASSERT_EQ(RoutesRegMsgCallback(E_ROUTES_CB_A, FakeCallback), BEST_OK);
    // ASSERT_EQ(RoutesSendMsg(E_ROUTES_CB_A, nullptr, 0), BEST_OK);
}

TEST_F(CoreTest, TestLogPrint)
{
    g_LogLevel = E_LOGLEVEL_OFF;
    printf("current log level: off\n");
    CORE_LogFatal("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogErr("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogWarn("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogInfo("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogDebug("hello world, myName is %s, age: %d", "lv", 29);

    g_LogLevel = E_LOGLEVEL_FATAL;
    printf("current log level: fatal\n");
    CORE_LogFatal("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogErr("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogWarn("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogInfo("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogDebug("hello world, myName is %s, age: %d", "lv", 29);

    g_LogLevel = E_LOGLEVEL_ERR;
    printf("current log level: err\n");
    CORE_LogFatal("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogErr("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogWarn("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogInfo("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogDebug("hello world, myName is %s, age: %d", "lv", 29);

    g_LogLevel = E_LOGLEVEL_WARN;
    printf("current log level: warn\n");
    CORE_LogFatal("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogErr("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogWarn("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogInfo("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogDebug("hello world, myName is %s, age: %d", "lv", 29);

    g_LogLevel = E_LOGLEVEL_INFO;
    printf("current log level: info\n");
    CORE_LogFatal("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogErr("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogWarn("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogInfo("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogDebug("hello world, myName is %s, age: %d", "lv", 29);

    g_LogLevel = E_LOGLEVEL_DEBUG;
    printf("current log level: debug\n");
    CORE_LogFatal("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogErr("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogWarn("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogInfo("hello world, myName is %s, age: %d", "lv", 29);
    CORE_LogDebug("hello world, myName is %s, age: %d", "lv", 29);
}

TEST_F(CoreTest, TestLogPrintToFile)
{
    CORE_LogFatalWriteToFile("hello world, myName is %s, age: %d", "lv", 29);
}

BEST_UINT32 Fake_TimerCallbackFunc(BEST_VOID *para1, BEST_VOID *para2,
                                   BEST_VOID *para3, BEST_VOID *para4)
{
    printf("Fake_TimerCallbackFunc done!\n");
    return BEST_OK;
}

#ifndef NOT_RUN_THREAD_POOL_UNIT_TEST
TEST_F(CoreTest, TestTimerInterval)
{
    ASSERT_EQ(CORE_ThreadPoolInit(), BEST_OK);
    ASSERT_EQ(CORE_TimerInit(), BEST_OK);
    BEST_UINT32            delay       = 3;
    CORE_TIMER_MODULE_TYPE eModuleType = E_CORE_TIMER_MODULE_LISTEN;

    BEST_STATUS uiRet3 = CORE_TimerStart(eModuleType, delay, E_CORE_TIMER_LOOP,
                                         Fake_TimerCallbackFunc, nullptr,
                                         nullptr, nullptr, nullptr);
    ASSERT_EQ(uiRet3, BEST_OK);
    printf("sleep 10\n");
    sleep(10);
    ASSERT_EQ(CORE_TimerStop(eModuleType), BEST_OK);
    printf("sleep 10\n");
    sleep(10);
    printf("sleep done!\n");
}
#endif
